import requests
from io import StringIO
import hashlib
from calc_manager.base.plugins import PluginObject

class BDFTransformer(PluginObject):
    """
    基于hm-bdf语法解析component的相关信息
    1. get_comps_info: 对应hypermesh结构树中components的信息,包括component名称、component id和prop名称
    2. get_comp_eids_ref: 获取每个component包含的单元id
    3. 目前这个逻辑的问题在于需要指定具体的bdf文件名称
    """

    def __init__(self, oss_url: str, local_path = None):
        if local_path:
            self.bdf_path = local_path
        else:
            response = requests.get(oss_url)
            response.raise_for_status() 

            #bdf_data = StringIO(response.text)

            file_hash = hashlib.md5(response.content).hexdigest()
            file_path = f"/tmp/{file_hash}.op2"

            with open(file_path, "wb") as f:
                f.write(response.content)
            print(f"Downloaded OP2 file from {oss_url} and saved to {file_path}")

            #self.bdf_path = bdf_path
            self.bdf_path = file_path

        if not self.check_bdf_generated():
            raise "the bdf file is not generated from hypermesh"
        else:
            with open(self.bdf_path, "rb") as file:
                self.lines = file.readlines()

    # 判断是否由hypermesh导出的bdf
    def check_bdf_generated(self, label=b"Generated by HyperMesh"):
        with open(self.bdf_path, "rb") as file:
            for line in file:
                if label in line:
                    # 由hypermesh导出的bdf
                    return 1
            else:
                # 非hypermesh导出的bdf
                return 0

    # HMMOVE 获取hmmove的索引位置
    def get_move_index(self):
        # 兼容bdf文件存在乱码
        start_marker = b"$HMMOVE"
        end_marker = b"$$"
        move_index = []
        start_index = 0
        for i, line in enumerate(self.lines):
            if i >= start_index and line.startswith(start_marker):
                for j, line in enumerate(self.lines):
                    if j > i and (line.startswith(end_marker) or line.startswith(start_marker)):
                        start_index = j
                        move_index.append((i, j))
                        break
        return move_index

    # 获取完整的eid描述行
    @staticmethod
    def get_move_eid(line: str):
        result = []
        for index in range(8, len(line), 8):
            data = line[index : index + 8].strip()
            try:
                eid = int(data)
            except:
                # print("THRU")
                result.append("THRU")
            else:
                result.append(eid)
        return result

    # 将THRU转化为真实的eid
    @staticmethod
    def expand_array(arr: list, label="THRU"):
        result = []
        for index, i in enumerate(arr):
            if i == label:
                temp = list(range(arr[index - 1] + 1, arr[index + 1]))
                result.extend(temp)
            else:
                result.append(i)
        return result

    # 获取cid与eids的对应关系
    def get_comp_eids_ref(self):
        # key: comp value: eids
        result = {}
        indexes = self.get_move_index()
        for index in indexes:
            content = self.lines[index[0] : index[1]]
            eids = []
            for i, line in enumerate(content):
                if i:
                    line_eids = BDFTransformer.get_move_eid(line.strip())
                    eids.extend(line_eids)
                else:
                    cid = int(line[8:].strip())
            if cid in result:
                result[cid].extend(BDFTransformer.expand_array(eids))
                pass
            else:
                result[cid] = BDFTransformer.expand_array(eids)
        return result

    def get_comp_by_eid(self, eid):
        result = self.get_comp_eids_ref()
        for k, v in result.items():
            if eid in v:
                return k

    # 获取所有comp的id、name和prop信息
    def get_comps_info(self):
        comps_info = []
        for line in self.lines:
            if line.startswith(b"$HMNAME COMP"):
                data = line.decode().split('"')
                comps_info.append(
                    {"cname": data[1], "cid": int(data[2].strip()), "pname": data[3]}
                )
        return comps_info
    
    # 根据g70_name获取所有的cid和所有的eids
    def get_comps_by_gname(self, gname):
        cids = []
        eids = []
        for k, v in self.get_comp_eids_ref().items():
            for comp_info in self.get_comps_info():
                if (k == comp_info["cid"]) and (comp_info["cname"].split("_")[0] == gname):
                    cids.append(k)
                    eids.extend(v)
        return cids, eids


            